package com.sz.ruichar.utils.system;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;

public class HttpUtils 
{
	private static Logger log = LoggerFactory.getLogger(HttpUtils.class);
	/**
	 * get
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doGet(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpGet request = new HttpGet(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }
        
        return httpClient.execute(request);
    }
	
	
	public static String doGet(String url, Map<String, String> params)throws Exception 
	{    	
		HttpClient httpClient = wrapClient(url);
		
		HttpGet request = new HttpGet(buildUrl(url, params));
		HttpResponse response = httpClient.execute(request);
		String result = "";
		int resultCode = response.getStatusLine().getStatusCode();
		if(200 == response.getStatusLine().getStatusCode())
		{
			result = EntityUtils.toString(response.getEntity());
		}
		else
		{
			result = "{error:"+resultCode+"}";
		}
		return result;
	}
	
	/**
	 * post form
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param bodys
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPost(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			Map<String, String> bodys)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (bodys != null) {
            List<NameValuePair> nameValuePairList = new ArrayList<NameValuePair>();

            for (String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Post String
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPost(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			String body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
        	request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }
	
	
	public static String doPost(String url, Map<String, String> params)throws Exception {    	
		HttpClient httpClient = wrapClient(url);
	
		HttpPost request = new HttpPost(buildUrl(url, params));
		HttpResponse response = httpClient.execute(request);
		String result = "";
		int resultCode = response.getStatusLine().getStatusCode();
		if(200 == response.getStatusLine().getStatusCode())
		{
			result = EntityUtils.toString(response.getEntity());
		}
		else
		{
			result = "{error:"+resultCode+"}";
		}
		return result;
	}

	public static String doPostJson(String url, Map<String, String>  mapParams)throws Exception {
		if(null == mapParams)
		{
			return null;
		}
		HttpClient httpClient = wrapClient(url);
		HttpPost post = new HttpPost(url);
		post.setHeader("Content-Type", "application/json;charset=UTF-8");
		post.setHeader("Accept", "application/json");
		post.setEntity(new StringEntity(JSONObject.toJSONString(mapParams), Charset.forName("UTF-8")));
		HttpResponse response = httpClient.execute(post);
		String result = "";
		int resultCode = response.getStatusLine().getStatusCode();
		if(200 == response.getStatusLine().getStatusCode())
		{
			result = EntityUtils.toString(response.getEntity(),"UTF-8");
		}
		else
		{
			result = "{error:"+resultCode+"}";
		}

		return  result;
	}
	

	/**
	 * Post String
	 * 重载一个post用于调用app接口进行回调通知
	 * @param url
	 * @param keySHA		签名，没有就用空字符串即可
	 * @param jsonParam	参数为json字符串
	 * @return
	 * @throws Exception
	 */
	/*public static String doPost(String url,String keySHA,JSONObject jsonParam)throws Exception {

		HttpPost method = new HttpPost(url);
		DefaultHttpClient httpClient = new DefaultHttpClient();
		String body = null;
		int status = 0;

		log.info("----------jsonParam:" + jsonParam.toString());

		if (method != null & jsonParam != null) {
			try {

				// 建立一个NameValuePair数组，用于存储欲传送的参数
				method.addHeader("Content-type","application/json; charset=utf-8");
				if(StringUtils.isNotBlank(keySHA)){
					method.addHeader("key",keySHA);
				}
				method.setHeader("Accept", "application/json");
				method.setEntity(new StringEntity(jsonParam.toString(), Charset.forName("UTF-8")));

				HttpResponse response = httpClient.execute(method);

				int statusCode = response.getStatusLine().getStatusCode();

				if (statusCode != HttpStatus.SC_OK) {
					status = 1;
				}

				//response转为字符串
				body = EntityUtils.toString(response.getEntity());

			} catch (IOException e) {
				// 网络错误
				status = 3;
			} finally {
				log.info("调用接口状态：" + status);
			}
		}
		return body;
	}*/

	/**
	 * Post stream
	 * 
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPost(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			byte[] body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPost request = new HttpPost(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
        	request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Put String
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPut(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			String body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
        	request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Put stream
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @param body
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doPut(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys, 
			byte[] body)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpPut request = new HttpPut(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }

        if (body != null) {
        	request.setEntity(new ByteArrayEntity(body));
        }

        return httpClient.execute(request);
    }
	
	/**
	 * Delete
	 *  
	 * @param host
	 * @param path
	 * @param method
	 * @param headers
	 * @param querys
	 * @return
	 * @throws Exception
	 */
	public static HttpResponse doDelete(String host, String path, String method, 
			Map<String, String> headers, 
			Map<String, String> querys)
            throws Exception {    	
    	HttpClient httpClient = wrapClient(host);

    	HttpDelete request = new HttpDelete(buildUrl(host, path, querys));
        for (Map.Entry<String, String> e : headers.entrySet()) {
        	request.addHeader(e.getKey(), e.getValue());
        }
        
        return httpClient.execute(request);
    }
	
	private static String buildUrl(String host, String path, Map<String, String> querys) throws UnsupportedEncodingException {
    	StringBuilder sbUrl = new StringBuilder();
    	sbUrl.append(host);
    	if (!StringUtils.isBlank(path)) {
    		sbUrl.append(path);
        }
    	if (null != querys) {
    		StringBuilder sbQuery = new StringBuilder();
        	for (Map.Entry<String, String> query : querys.entrySet()) {
        		if (0 < sbQuery.length()) {
        			sbQuery.append("&");
        		}
        		if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
        			sbQuery.append(query.getValue());
                }
        		if (!StringUtils.isBlank(query.getKey())) {
        			sbQuery.append(query.getKey());
        			if (!StringUtils.isBlank(query.getValue())) {
        				sbQuery.append("=");
        				sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
        			}        			
                }
        	}
        	if (0 < sbQuery.length()) {
        		sbUrl.append("?").append(sbQuery);
        	}
        }
    	
    	return sbUrl.toString();
    }
	
	private static String buildUrl(String url, Map<String, String> params) throws UnsupportedEncodingException {
    	StringBuilder sbUrl = new StringBuilder();
    	sbUrl.append(url);
    	if (null != params) {
    		StringBuilder sbQuery = new StringBuilder();
        	for (Map.Entry<String, String> query : params.entrySet()) {
        		if (0 < sbQuery.length()) {
        			sbQuery.append("&");
        		}
        		if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
        			sbQuery.append(query.getValue());
                }
        		if (!StringUtils.isBlank(query.getKey())) {
        			sbQuery.append(query.getKey());
        			if (!StringUtils.isBlank(query.getValue())) {
        				sbQuery.append("=");
        				sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
        			}        			
                }
        	}
        	if (0 < sbQuery.length()) {
        		sbUrl.append("?").append(sbQuery);
        	}
        }
    	
    	return sbUrl.toString();
    }
	
	private static HttpClient wrapClient(String host) {
		HttpClient httpClient = new DefaultHttpClient();
		if (host.startsWith("https://")) {
			sslClient(httpClient);
		}
		
		return httpClient;
	}
	
	private static void sslClient(HttpClient httpClient) {
        try {
            SSLContext ctx = SSLContext.getInstance("TLS");
            X509TrustManager tm = new X509TrustManager() {
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }
                public void checkClientTrusted(X509Certificate[] xcs, String str) {
                	
                }
                public void checkServerTrusted(X509Certificate[] xcs, String str) {
                	
                }
            };
            ctx.init(null, new TrustManager[] { tm }, null);
            SSLSocketFactory ssf = new SSLSocketFactory(ctx);
            ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
            ClientConnectionManager ccm = httpClient.getConnectionManager();
            SchemeRegistry registry = ccm.getSchemeRegistry();
            registry.register(new Scheme("https", 443, ssf));
        } catch (KeyManagementException ex) {
            throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
        	throw new RuntimeException(ex);
        }
    }
	
	public final static String getIpAddress(HttpServletRequest request) 
	{  
        // 获取请求主机IP地址,如果通过代理进来，则透过防火墙获取真实IP地址 
	   String ip = request.getHeader("X-Forwarded-For");  
		try
		{
			log.info("getIpAddress(HttpServletRequest) - X-Forwarded-For - String ip={}", ip);
	  
	        if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) 
	        {  
	            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) 
	            {  
	                ip = request.getHeader("Proxy-Client-IP");  
                    log.info("getIpAddress(HttpServletRequest) - Proxy-Client-IP - String ip={}", ip);
	            }  
	            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) 
	            {  
	                ip = request.getHeader("WL-Proxy-Client-IP");  
                    log.info("getIpAddress(HttpServletRequest) - WL-Proxy-Client-IP - String ip={}",ip);
	            }  
	            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) 
	            {  
	                ip = request.getHeader("HTTP_CLIENT_IP");  
                    log.info("getIpAddress(HttpServletRequest) - HTTP_CLIENT_IP - String ip={}",ip);
	            }  
	            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) 
	            {  
	                ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
                    log.info("getIpAddress(HttpServletRequest) - HTTP_X_FORWARDED_FOR - String ip={}", ip);
	            }  
	            if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) 
	            {  
	                ip = request.getRemoteAddr();  
                    log.info("getIpAddress(HttpServletRequest) - getRemoteAddr - String ip={}" , ip);
	            }  
	        } 
	        else if (ip.length() > 15) 
	        {  
	            String[] ips = ip.split(",");  
	            for (int index = 0; index < ips.length; index++) 
	            {  
	                String strIp = (String) ips[index];  
	                if (!("unknown".equalsIgnoreCase(strIp))) 
	                {  
	                    ip = strIp;  
	                    break;  
	                }  
	            }  
	        }  
		}
		catch(Exception e)
		{
			log.error("===============Exception e={}",e);
		}
     
        
        return ip;  
    } 
	
}